package com.jeesite.modules.web;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import com.jeesite.modules.service.DonationService;
import com.jeesite.modules.service.PaymentService;
import com.jeesite.modules.dto.PaymentOrderDto;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 支付宝测试控制器 - 直接调用支付宝SDK
 * @author LaVenderGong
 * @version 2025-08-18
 */
@RestController
@RequestMapping("/alipay-test")
@PropertySource("classpath:config/alipay.properties")
public class AlipayTestController {

    private static final Logger logger = LoggerFactory.getLogger(AlipayTestController.class);

    // 简单的内存订单存储（生产环境应该使用数据库）
    private static final Map<String, Map<String, Object>> orderStorage = new ConcurrentHashMap<>();

    // 从配置文件中读取支付宝配置
    @Value("${alipay.app-id}")
    private String appId;

    @Value("${alipay.private-key}")
    private String privateKey;

    @Value("${alipay.public-key}")
    private String alipayPublicKey;

    @Value("${alipay.gateway-url}")
    private String gatewayUrl;

    @Value("${alipay.notify-url}")
    private String notifyUrl;

    @Autowired
    private DonationService donationService;

    @Autowired
    private PaymentService paymentService;

    @PostMapping("/precreate")
    public Map<String, Object> testPrecreate(@RequestBody Map<String, Object> request) {
        Map<String, Object> result = new HashMap<>();

        try {
            String orderId = (String) request.get("orderId");
            String amount = request.getOrDefault("amount", "0.01").toString();
            String subject = (String) request.getOrDefault("subject", "测试订单");

            // 获取用户信息
            String donorName = (String) request.get("donorName");
            String gameAccountId = (String) request.get("gameAccountId");
            String gameNickname = (String) request.get("gameNickname");
            String contactInfo = (String) request.get("contactInfo");
            String message = (String) request.get("message");
            String paymentMethod = (String) request.getOrDefault("paymentMethod", "alipay");

            logger.info("支付宝预创建请求: orderId={}, amount={}, subject={}", orderId, amount, subject);
            logger.info("用户信息: donorName={}, gameAccountId={}, gameNickname={}", donorName, gameAccountId, gameNickname);
            logger.info("支付宝配置: appId={}, gatewayUrl={}", appId, gatewayUrl);
            logger.info("私钥长度: {}, 公钥长度: {}", privateKey != null ? privateKey.length() : 0, alipayPublicKey != null ? alipayPublicKey.length() : 0);

            // 创建支付宝客户端
            AlipayClient alipayClient = new DefaultAlipayClient(
                gatewayUrl, appId, privateKey, "json", "UTF-8", alipayPublicKey, "RSA2");

            logger.info("支付宝客户端创建成功");

            // 创建预创建请求
            AlipayTradePrecreateRequest alipayRequest = new AlipayTradePrecreateRequest();

            // 设置回调地址
            alipayRequest.setNotifyUrl(notifyUrl);

            // 设置业务参数
            String bizContent = String.format(
                "{\"out_trade_no\":\"%s\",\"total_amount\":\"%s\",\"subject\":\"%s\"}",
                orderId, amount, subject);
            alipayRequest.setBizContent(bizContent);

            // 执行请求
            logger.info("开始调用支付宝预创建API...");
            AlipayTradePrecreateResponse response = alipayClient.execute(alipayRequest);
            logger.info("支付宝API调用完成，响应码: {}", response.getCode());

            if (response.isSuccess()) {
                result.put("success", true);
                result.put("message", "支付宝预创建成功");

                Map<String, Object> data = new HashMap<>();
                data.put("qrCode", response.getQrCode());
                data.put("qrCodeUrl", response.getQrCode());
                data.put("qrCodeImageUrl", "/alipay-test/qrcode/" + orderId); // 二维码图片URL
                data.put("orderId", orderId);
                data.put("outTradeNo", response.getOutTradeNo());



                result.put("data", data);
                logger.info("二维码生成成功: {}", response.getQrCode());

                // 保存订单信息到内存存储
                Map<String, Object> orderInfo = new HashMap<>();
                orderInfo.put("orderId", orderId);
                orderInfo.put("outTradeNo", response.getOutTradeNo());
                orderInfo.put("amount", amount);
                orderInfo.put("subject", subject);
                orderInfo.put("qrCode", response.getQrCode());
                orderInfo.put("status", "WAIT_BUYER_PAY"); // 等待买家付款
                orderInfo.put("createTime", LocalDateTime.now().toString());
                orderStorage.put(orderId, orderInfo);
                logger.info("订单信息已保存: {}", orderId);

                // 同时保存到数据库
                try {
                    logger.info("保存捐赠信息: donorName={}, gameAccountId={}, gameNickname={}, contactInfo={}",
                        donorName, gameAccountId, gameNickname, contactInfo);

                    boolean dbResult = donationService.createDonationAndPaymentOrder(
                        orderId,
                        new java.math.BigDecimal(amount),
                        donorName,
                        message,
                        paymentMethod,
                        gameAccountId,
                        gameNickname,
                        contactInfo
                    );
                    if (dbResult) {
                        logger.info("订单数据库记录创建成功: {}", orderId);
                    } else {
                        logger.warn("订单数据库记录创建失败: {}", orderId);
                    }
                } catch (Exception e) {
                    logger.error("创建订单数据库记录时发生异常: {}", orderId, e);
                }
            } else {
                result.put("success", false);
                result.put("message", "支付宝预创建失败: " + response.getMsg());
                result.put("code", response.getCode());
                result.put("subCode", response.getSubCode());
                result.put("subMsg", response.getSubMsg());
            }

        } catch (AlipayApiException e) {
            result.put("success", false);
            result.put("message", "支付宝API异常: " + e.getMessage());
            result.put("errorCode", e.getErrCode());
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "系统异常: " + e.getMessage());
        }

        return result;
    }

    @GetMapping("/query/{orderId}")
    public Map<String, Object> queryPaymentStatus(@PathVariable String orderId) {
        Map<String, Object> result = new HashMap<>();

        try {
            // 首先检查本地订单状态
            if (paymentService != null) {
                PaymentOrderDto localOrder = paymentService.getPaymentOrderDto(orderId);
                if (localOrder != null) {
                    // 如果本地订单状态是已取消、已失败或已成功，直接返回本地状态
                    if (PaymentOrderDto.STATUS_CANCELLED.equals(localOrder.getStatus()) ||
                        PaymentOrderDto.STATUS_FAILED.equals(localOrder.getStatus()) ||
                        PaymentOrderDto.STATUS_SUCCESS.equals(localOrder.getStatus())) {

                        result.put("success", true);
                        result.put("message", "查询成功");

                        Map<String, Object> data = new HashMap<>();
                        data.put("orderId", orderId);
                        data.put("tradeStatus", getAlipayTradeStatus(localOrder.getStatus()));
                        data.put("localStatus", localOrder.getStatus());
                        data.put("amount", localOrder.getAmount());

                        result.put("data", data);
                        logger.info("返回本地订单状态: {} -> {}", orderId, localOrder.getStatus());
                        return result;
                    }
                }
            }

            // 创建支付宝客户端
            AlipayClient alipayClient = new DefaultAlipayClient(
                gatewayUrl, appId, privateKey, "json", "UTF-8", alipayPublicKey, "RSA2");

            // 创建查询请求
            AlipayTradeQueryRequest alipayRequest = new AlipayTradeQueryRequest();

            // 设置业务参数
            String bizContent = String.format("{\"out_trade_no\":\"%s\"}", orderId);
            alipayRequest.setBizContent(bizContent);

            // 执行请求
            AlipayTradeQueryResponse response = alipayClient.execute(alipayRequest);

            if (response.isSuccess()) {
                result.put("success", true);
                result.put("message", "查询成功");

                Map<String, Object> data = new HashMap<>();
                data.put("orderId", orderId);
                data.put("tradeNo", response.getTradeNo());
                data.put("tradeStatus", response.getTradeStatus());
                data.put("totalAmount", response.getTotalAmount());
                data.put("buyerPayAmount", response.getBuyerPayAmount());

                result.put("data", data);

                // 如果订单存在于内存中，更新状态
                if (orderStorage.containsKey(orderId)) {
                    Map<String, Object> orderInfo = orderStorage.get(orderId);
                    orderInfo.put("tradeNo", response.getTradeNo());
                    orderInfo.put("tradeStatus", response.getTradeStatus());
                    orderInfo.put("updateTime", LocalDateTime.now().toString());
                    orderStorage.put(orderId, orderInfo);
                }

                // 重要：同时更新数据库中的订单状态
                if (paymentService != null) {
                    String tradeStatus = response.getTradeStatus();
                    if ("TRADE_SUCCESS".equals(tradeStatus)) {
                        // 支付成功，更新数据库状态
                        Map<String, String> callbackData = new HashMap<>();
                        callbackData.put("trade_no", response.getTradeNo());
                        callbackData.put("trade_status", tradeStatus);
                        callbackData.put("total_amount", response.getTotalAmount());
                        callbackData.put("buyer_pay_amount", response.getBuyerPayAmount());

                        paymentService.updatePaymentSuccess(orderId, response.getTradeNo(), callbackData);
                        logger.info("查询发现支付成功，已更新数据库状态: {} -> {}", orderId, tradeStatus);
                    } else if ("TRADE_CLOSED".equals(tradeStatus)) {
                        // 交易关闭，更新数据库状态
                        Map<String, String> callbackData = new HashMap<>();
                        callbackData.put("trade_no", response.getTradeNo());
                        callbackData.put("trade_status", tradeStatus);

                        paymentService.updatePaymentClosed(orderId, response.getTradeNo(), callbackData);
                        logger.info("查询发现交易关闭，已更新数据库状态: {} -> {}", orderId, tradeStatus);
                    }
                }

                logger.info("订单状态查询成功: {} -> {}", orderId, response.getTradeStatus());
            } else {
                // 检查是否是交易不存在的情况
                if ("ACQ.TRADE_NOT_EXIST".equals(response.getSubCode())) {
                    // 交易不存在，可能是未支付或已取消，返回待支付状态
                    result.put("success", true);
                    result.put("message", "订单待支付");

                    Map<String, Object> data = new HashMap<>();
                    data.put("orderId", orderId);
                    data.put("tradeStatus", "WAIT_BUYER_PAY");
                    data.put("localStatus", "CREATED");

                    result.put("data", data);
                    logger.info("订单未在支付宝找到，返回待支付状态: {}", orderId);
                } else {
                    // 其他错误情况
                    result.put("success", false);
                    result.put("message", "查询失败: " + response.getMsg());
                    result.put("code", response.getCode());
                    result.put("subCode", response.getSubCode());
                    result.put("subMsg", response.getSubMsg());

                    Map<String, Object> data = new HashMap<>();
                    data.put("orderId", orderId);
                    data.put("tradeStatus", "UNKNOWN");

                    result.put("data", data);
                    logger.warn("支付宝查询失败: {} - {}", orderId, response.getMsg());
                }
            }

        } catch (AlipayApiException e) {
            result.put("success", false);
            result.put("message", "支付宝API异常: " + e.getMessage());
            result.put("errorCode", e.getErrCode());
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "系统异常: " + e.getMessage());
        }

        return result;
    }

    /**
     * 支付宝支付回调处理
     */
    @PostMapping("/notify")
    public String paymentNotify(@RequestParam Map<String, String> params) {
        logger.info("收到支付宝回调通知: {}", params);

        try {
            // 获取订单号
            String outTradeNo = params.get("out_trade_no");
            String tradeStatus = params.get("trade_status");
            String tradeNo = params.get("trade_no");

            if (outTradeNo != null) {
                // 更新内存中的订单状态
                if (orderStorage.containsKey(outTradeNo)) {
                    Map<String, Object> orderInfo = orderStorage.get(outTradeNo);
                    orderInfo.put("tradeStatus", tradeStatus);
                    orderInfo.put("tradeNo", tradeNo);
                    orderInfo.put("notifyTime", LocalDateTime.now().toString());
                    orderStorage.put(outTradeNo, orderInfo);
                }

                // 更新数据库中的订单状态
                if (paymentService != null) {
                    if ("TRADE_SUCCESS".equals(tradeStatus)) {
                        // 支付成功，更新订单状态
                        paymentService.updatePaymentSuccess(outTradeNo, tradeNo, params);
                        logger.info("支付成功，订单状态已更新: {} -> {}", outTradeNo, tradeStatus);
                    } else if ("TRADE_CLOSED".equals(tradeStatus)) {
                        // 交易关闭，更新订单状态
                        paymentService.updatePaymentClosed(outTradeNo, tradeNo, params);
                        logger.info("交易关闭，订单状态已更新: {} -> {}", outTradeNo, tradeStatus);
                    }
                }

                logger.info("订单状态已更新: {} -> {}", outTradeNo, tradeStatus);
            }

            return "success"; // 返回success告诉支付宝处理成功
        } catch (Exception e) {
            logger.error("处理支付回调失败", e);
            return "fail";
        }
    }



    /**
     * 获取订单信息
     */
    @GetMapping("/order/{orderId}")
    public Map<String, Object> getOrder(@PathVariable String orderId) {
        Map<String, Object> result = new HashMap<>();

        if (orderStorage.containsKey(orderId)) {
            result.put("success", true);
            result.put("data", orderStorage.get(orderId));
        } else {
            result.put("success", false);
            result.put("message", "订单不存在");
        }

        return result;
    }

    /**
     * 获取所有订单
     */
    @GetMapping("/orders")
    public Map<String, Object> getAllOrders() {
        Map<String, Object> result = new HashMap<>();
        result.put("success", true);
        result.put("data", orderStorage);
        result.put("count", orderStorage.size());
        return result;
    }




    /**
     * 检查支付宝配置
     */
    @GetMapping("/check-config")
    public Map<String, Object> checkConfig() {
        Map<String, Object> result = new HashMap<>();

        result.put("appId", appId);
        result.put("gatewayUrl", gatewayUrl);
        result.put("notifyUrl", notifyUrl);
        result.put("privateKeyLength", privateKey != null ? privateKey.length() : 0);
        result.put("publicKeyLength", alipayPublicKey != null ? alipayPublicKey.length() : 0);
        result.put("privateKeyPrefix", privateKey != null && privateKey.length() > 20 ? privateKey.substring(0, 20) + "..." : "null");
        result.put("publicKeyPrefix", alipayPublicKey != null && alipayPublicKey.length() > 20 ? alipayPublicKey.substring(0, 20) + "..." : "null");

        // 检查配置是否完整
        boolean configComplete = appId != null && !appId.isEmpty()
                               && privateKey != null && !privateKey.isEmpty()
                               && alipayPublicKey != null && !alipayPublicKey.isEmpty()
                               && gatewayUrl != null && !gatewayUrl.isEmpty();
        result.put("configComplete", configComplete);

        return result;
    }

    @GetMapping("/test-page")
    @ResponseBody
    public String testPage() {
        return "<!DOCTYPE html><html><head><title>支付宝测试</title></head><body>" +
               "<h1>支付宝二维码生成测试</h1>" +
               "<div><label>订单号:</label><input type='text' id='orderId' value='TEST_ORDER_001'></div>" +
               "<div><label>金额:</label><input type='number' id='amount' value='0.01' step='0.01'></div>" +
               "<div><label>商品名称:</label><input type='text' id='subject' value='KBB服务器捐赠测试'></div>" +
               "<button onclick='createOrder()'>生成支付宝二维码</button>" +
               "<button onclick='queryOrder()'>查询订单状态</button>" +
               "<div id='result'></div>" +
               "<script>" +
               "async function createOrder() {" +
               "  const orderId = document.getElementById('orderId').value;" +
               "  const amount = document.getElementById('amount').value;" +
               "  const subject = document.getElementById('subject').value;" +
               "  document.getElementById('result').innerHTML = '正在生成...';" +
               "  try {" +
               "    const response = await fetch('/alipay-test/precreate', {" +
               "      method: 'POST'," +
               "      headers: {'Content-Type': 'application/json'}," +
               "      body: JSON.stringify({orderId, amount, subject})" +
               "    });" +
               "    const data = await response.json();" +
               "    document.getElementById('result').innerHTML = '<pre>' + JSON.stringify(data, null, 2) + '</pre>';" +
               "  } catch (error) {" +
               "    document.getElementById('result').innerHTML = '错误: ' + error.message;" +
               "  }" +
               "}" +
               "async function queryOrder() {" +
               "  const orderId = document.getElementById('orderId').value;" +
               "  try {" +
               "    const response = await fetch('/js/api/alipay-test/query/' + orderId);" +
               "    const data = await response.json();" +
               "    document.getElementById('result').innerHTML = '<pre>' + JSON.stringify(data, null, 2) + '</pre>';" +
               "  } catch (error) {" +
               "    document.getElementById('result').innerHTML = '错误: ' + error.message;" +
               "  }" +
               "}" +
               "document.addEventListener('DOMContentLoaded', function() {" +
               "  document.getElementById('orderId').value = 'TEST_ORDER_' + new Date().getTime();" +
               "});" +
               "</script></body></html>";
    }

    /**
     * 生成二维码图片
     */
    @GetMapping("/qrcode/{orderId}")
    public ResponseEntity<byte[]> generateQrCode(@PathVariable String orderId) {
        try {
            // 首先查询订单获取支付链接
            String qrCodeUrl = getQrCodeUrlByOrderId(orderId);
            if (qrCodeUrl == null) {
                return ResponseEntity.notFound().build();
            }

            // 生成二维码图片
            byte[] qrCodeImage = generateQrCodeImage(qrCodeUrl, 300, 300);

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.IMAGE_PNG);
            headers.setContentLength(qrCodeImage.length);
            headers.setCacheControl("no-cache");

            return ResponseEntity.ok()
                    .headers(headers)
                    .body(qrCodeImage);

        } catch (Exception e) {
            logger.error("生成二维码失败: {}", e.getMessage(), e);
            return ResponseEntity.internalServerError().build();
        }
    }

    /**
     * 根据订单ID获取二维码URL - 从订单存储中获取真实的二维码URL
     */
    private String getQrCodeUrlByOrderId(String orderId) {
        if (orderStorage.containsKey(orderId)) {
            Map<String, Object> orderInfo = orderStorage.get(orderId);
            String qrCode = (String) orderInfo.get("qrCode");
            if (qrCode != null && !qrCode.isEmpty()) {
                return qrCode;
            }
        }

        // 如果订单不存在或没有二维码，返回null
        logger.warn("订单 {} 不存在或没有二维码信息", orderId);
        return null;
    }

    /**
     * 生成二维码图片
     */
    private byte[] generateQrCodeImage(String text, int width, int height) throws WriterException, IOException {
        QRCodeWriter qrCodeWriter = new QRCodeWriter();

        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        hints.put(EncodeHintType.MARGIN, 1);

        BitMatrix bitMatrix = qrCodeWriter.encode(text, BarcodeFormat.QR_CODE, width, height, hints);

        BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        bufferedImage.createGraphics();

        Graphics2D graphics = (Graphics2D) bufferedImage.getGraphics();
        graphics.setColor(Color.WHITE);
        graphics.fillRect(0, 0, width, height);
        graphics.setColor(Color.BLACK);

        for (int i = 0; i < bitMatrix.getWidth(); i++) {
            for (int j = 0; j < bitMatrix.getHeight(); j++) {
                if (bitMatrix.get(i, j)) {
                    graphics.fillRect(i, j, 1, 1);
                }
            }
        }

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ImageIO.write(bufferedImage, "PNG", outputStream);
        return outputStream.toByteArray();
    }

    /**
     * 将本地订单状态转换为支付宝交易状态
     */
    private String getAlipayTradeStatus(String localStatus) {
        switch (localStatus) {
            case PaymentOrderDto.STATUS_SUCCESS:
                return "TRADE_SUCCESS";
            case PaymentOrderDto.STATUS_CANCELLED:
                return "TRADE_CLOSED";
            case PaymentOrderDto.STATUS_FAILED:
                return "TRADE_CLOSED";
            case PaymentOrderDto.STATUS_PAYING:
                return "WAIT_BUYER_PAY";
            case PaymentOrderDto.STATUS_CREATED:
                return "WAIT_BUYER_PAY";
            default:
                return "UNKNOWN";
        }
    }
}